#include "lwip_comm.h" 
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "ethernetif.h" 
#include "lwip/ip4_frag.h"
#include "lwip/tcpip.h" 
#include "usart.h"  
#include <stdio.h>
#include "ucos_ii.h" 
#include "malloc.h"
 
__lwip_dev lwipdev;
struct netif lwip_netif;
 
extern sys_mbox_t mbox;
extern u32 memp_get_memorysize(void);
extern u8_t *memp_memory;
extern u8_t *ram_heap;
extern sys_mbox_t mbox;

extern u8_t netif_num;
extern struct tcp_seg inseg;
extern struct tcp_hdr *tcphdr;
extern struct ip_hdr *iphdr;
extern u32_t seqno, ackno;
extern u16_t tcplen;
extern u8_t recv_flags;
extern struct pbuf *recv_data;
extern u8_t etharp_cached_entry;
extern u16_t ip_id;
extern struct ip_reassdata *reassdatagrams;
extern u16_t ip_reass_pbufcount;
extern u8_t *ram;
extern struct mem *ram_end;
extern struct mem *lfree;
extern sys_mutex_t mem_mutex;

extern void ip_reass_timer(void *arg);
extern void arp_timer(void *arg);
extern void dhcp_timer_coarse(void *arg);
extern void dhcp_timer_fine(void *arg);
extern struct sys_timeo *next_timeout;
extern int tcpip_tcp_timer_active;

OS_STK * TCPIP_THREAD_TASK_STK;	 

//lwip DHCP
#define LWIP_DHCP_TASK_PRIO       		9 

#define LWIP_DHCP_STK_SIZE  		    128

OS_STK * LWIP_DHCP_TASK_STK;	

void lwip_dhcp_task(void *pdata); 

void lwip_packet_handler(void)
{
	ethernetif_input(&lwip_netif);
}

u8 lwip_comm_mem_malloc(void)
{
	u32 mempsize;
	u32 ramheapsize; 
	mempsize=memp_get_memorysize();
	memp_memory=mymalloc(SRAMIN,mempsize);
	ramheapsize=LWIP_MEM_ALIGN_SIZE(MEM_SIZE)+2*LWIP_MEM_ALIGN_SIZE(4*3)+MEM_ALIGNMENT;
	ram_heap=mymalloc(SRAMIN,ramheapsize);
	TCPIP_THREAD_TASK_STK=mymalloc(SRAMIN,TCPIP_THREAD_STACKSIZE*4);
	LWIP_DHCP_TASK_STK=mymalloc(SRAMIN,LWIP_DHCP_STK_SIZE*4);
	if(!memp_memory||!ram_heap||!TCPIP_THREAD_TASK_STK||!LWIP_DHCP_TASK_STK)
	{
		lwip_comm_mem_free();
		return 1;
	}
	return 0;	
}

void lwip_comm_mem_free(void)
{ 	
	myfree(SRAMIN,memp_memory);
	myfree(SRAMIN,ram_heap);
	myfree(SRAMIN,TCPIP_THREAD_TASK_STK);
	myfree(SRAMIN,LWIP_DHCP_TASK_STK);
}

void lwip_comm_default_ip_set(__lwip_dev *lwipx)
{
	u32 sn0;

	sn0=*(vu32*)(0x1FFF7A10);

	lwipx->remoteip[0]=192;
	lwipx->remoteip[1]=168;
	lwipx->remoteip[2]=1;
	lwipx->remoteip[3]=11;

	lwipx->mac[0]=2;
	lwipx->mac[1]=0;
	lwipx->mac[2]=0;
	lwipx->mac[3]=(sn0>>16)&0XFF;
	lwipx->mac[4]=(sn0>>8)&0XFFF;
	lwipx->mac[5]=sn0&0XFF;

	lwipx->ip[0]=192;
	lwipx->ip[1]=168;
	lwipx->ip[2]=1;
	lwipx->ip[3]=30;

	lwipx->netmask[0]=255;
	lwipx->netmask[1]=255;
	lwipx->netmask[2]=255;
	lwipx->netmask[3]=0;

	lwipx->gateway[0]=192;
	lwipx->gateway[1]=168;
	lwipx->gateway[2]=1;
	lwipx->gateway[3]=1;
	lwipx->dhcpstatus=0;
} 

u8 lwip_comm_init(void)
{
	OS_CPU_SR cpu_sr;
	struct netif *Netif_Init_Flag;
	struct ip4_addr ipaddr;
	struct ip4_addr netmask;
	struct ip4_addr gw;
	if(ETH_Mem_Malloc())return 1;
	if(lwip_comm_mem_malloc())return 1;
	if(LAN8720_Init())return 2;
	tcpip_init(NULL,NULL);
	lwip_comm_default_ip_set(&lwipdev);
#if LWIP_DHCP
	ipaddr.addr = 0;
	netmask.addr = 0;
	gw.addr = 0;
#else
	IP4_ADDR(&ipaddr,lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
	IP4_ADDR(&netmask,lwipdev.netmask[0],lwipdev.netmask[1] ,lwipdev.netmask[2],lwipdev.netmask[3]);
	IP4_ADDR(&gw,lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
#endif
	OS_ENTER_CRITICAL();
	Netif_Init_Flag = netif_add(&lwip_netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
	OS_EXIT_CRITICAL();
	if(Netif_Init_Flag==NULL)return 3;
	else
	{
		netif_set_default(&lwip_netif);
		netif_set_up(&lwip_netif);
	}
	return 0;
}   

#if LWIP_DHCP
void lwip_comm_dhcp_creat(void)
{
	OS_CPU_SR cpu_sr;
	OS_ENTER_CRITICAL();
	OSTaskCreate(lwip_dhcp_task,(void*)0,(OS_STK*)&LWIP_DHCP_TASK_STK[LWIP_DHCP_STK_SIZE-1],LWIP_DHCP_TASK_PRIO);
	OS_EXIT_CRITICAL();
}

void lwip_comm_dhcp_delete(void)
{
	dhcp_stop(&lwip_netif);
	OSTaskDel(LWIP_DHCP_TASK_PRIO);
}

void lwip_dhcp_task(void *pdata)
{
	u32 ip=0,netmask=0,gw=0;
	dhcp_start(&lwip_netif);
	lwipdev.dhcpstatus=0;
	printf("Looking for dhcp server..........\r\n");
	lwipdev.dhcpstatus=1;
	while(1)
	{ 
		printf("Getting ip from dhcp server...\r\n");
		ip=lwip_netif.ip_addr.addr;
		netmask=lwip_netif.netmask.addr;
		gw=lwip_netif.gw.addr;
		if(ip!=0)
		{
			lwipdev.dhcpstatus=2;
 			printf("MAC addr:...........%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
			lwipdev.ip[3]=(uint8_t)(ip>>24); 
			lwipdev.ip[2]=(uint8_t)(ip>>16);
			lwipdev.ip[1]=(uint8_t)(ip>>8);
			lwipdev.ip[0]=(uint8_t)(ip);
			printf("IP addr:............%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
			lwipdev.netmask[3]=(uint8_t)(netmask>>24);
			lwipdev.netmask[2]=(uint8_t)(netmask>>16);
			lwipdev.netmask[1]=(uint8_t)(netmask>>8);
			lwipdev.netmask[0]=(uint8_t)(netmask);
			printf("Netmask:............%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
			lwipdev.gateway[3]=(uint8_t)(gw>>24);
			lwipdev.gateway[2]=(uint8_t)(gw>>16);
			lwipdev.gateway[1]=(uint8_t)(gw>>8);
			lwipdev.gateway[0]=(uint8_t)(gw);
			printf("Getway:.............%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
			break;
		}
		#if 0
		else if(lwip_netif.dhcp->tries>LWIP_MAX_DHCP_TRIES)
		{  
			lwipdev.dhcpstatus=0XFF;
			IP4_ADDR(&(lwip_netif.ip_addr),lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
			IP4_ADDR(&(lwip_netif.netmask),lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
			IP4_ADDR(&(lwip_netif.gw),lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
			printf("DHCP timeout, using static ip...\r\n");
			printf("MAC:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
			printf("IP addr:............%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
			printf("Netmask:............%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
			printf("Gateway:............%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
			break;
		}
		#endif
		delay_ms(500);
	}
	lwip_comm_dhcp_delete();
}
#endif 

